Previous Book Contents Book Index Next

Inside Macintosh: Overview /
Chapter 9 - Processes


Checking the Operating Environment

Calling ExitToShell is the preferred way to terminate your application if for some reason you don't want to return to your main event loop. You might also want to call DoBadError to terminate your application before you even get to the main event loop. This might happen if your application requires system software routines that aren't available in all operating environments. In general, if your application uses any system software routines that aren't available in all operating environments, you need to make sure that they are available in the current environment. Otherwise, your application will crash.

For example, the Venn Diagrammer application uses the FindFolder function to find the Preferences folder containing the application's preferences file (see Listing 3-3 on page 62). Because FindFolder was introduced in system software version 7.0, Venn Diagrammer will crash if it calls FindFolder when running in an earlier system software version.

To avoid crashing in environments that don't support the FindFolder function, the Venn Diagrammer application makes sure that the function is available before calling it. It calls the Gestalt function to see if FindFolder is present, as shown in Listing 9-6.

Listing 9-6 Checking that FindFolder is present

FUNCTION IsFindFolder: Boolean;
VAR
   myResult:   OSErr;
   myFeature:  LongInt;
BEGIN
   IsFindFolder := FALSE;        {assume it's not available}
   myResult := Gestalt(gestaltFindFolderAttr, myFeature);
   IF myResult = noErr THEN 
      IsFindFolder := BTST(myFeature, gestaltFindFolderPresent);
END;
The Gestalt function is part of the Gestalt Manager, which you can use to determine what software and hardware features are available in the current operating environment. When passed the gestaltFindFolderAttr selector code, the Gestalt function fills in the long integer passed in its second parameter (myFeature) with a bit field that encodes information about the features of the FindFolder function. Currently only one bit is defined, specified using the constant gestaltFindFolderPresent. If that bit is set, then FindFolder is present in the operating environment. The Venn Diagrammer application calls IsFindFolder as follows (see Listing 3-3 on page 62):

IF IsFindFolder THEN
   myResult := FindFolder(kOnSystemDisk, kPreferencesFolderType,
                           kDontCreateFolder, myVRefNum, myDirID);
Note
For complete details about using the Gestalt function to determine the features of the current operating environment, see the chapter "Gestalt Manager" in Inside Macintosh: Operating System Utilities.
If FindFolder function isn't available, Venn Diagrammer looks in the default directory instead of in the Preferences folder for the user's preferences file. This isn't the best strategy possible, but it's good enough for a simple application like Venn Diagrammer. More generally, however, you need to decide what the base system software requirements of your application are and how you want to react if necessary services aren't available. In some cases, working around a problem isn't so easy. In those cases, informing the user that your software won't run in the current system configuration and then exiting is probably the right thing to do.

A second way to determine the availability of a particular system software routine is to test directly for the existence of the routine by inspecting its trap number (a number that identifies each system software routine), using the technique illustrated in Listing 9-7. You should use this method to test for the existence of routines not included in managers about which Gestalt can report.

Listing 9-7 Determining whether a trap is available

FUNCTION NumToolboxTraps: Integer;
BEGIN
   IF NGetTrapAddress(_InitGraf, ToolTrap) = 
                     NGetTrapAddress($AA6E, ToolTrap) THEN
      NumToolboxTraps := $200
   ELSE
      NumToolboxTraps := $400;
END;

FUNCTION GetTrapType (theTrap: Integer): TrapType;
CONST
   TrapMask = $0800;
BEGIN
   IF BAND(theTrap, TrapMask) > 0 THEN
      GetTrapType := ToolTrap
   ELSE
      GetTrapType := OSTrap;
END;

FUNCTION TrapAvailable (theTrap: Integer): Boolean;
VAR
   tType:      TrapType;
BEGIN
   tType := GetTrapType(theTrap);
   IF tType = ToolTrap THEN
   BEGIN
      theTrap := BAND(theTrap, $07FF);
      IF theTrap >= NumToolboxTraps THEN
         theTrap := _Unimplemented;
   END;
   TrapAvailable := NGetTrapAddress(theTrap, tType) <>                     NGetTrapAddress(_Unimplemented, ToolTrap);
END;
Listing 9-8 shows how to use the TrapAvailable function defined in Listing 9-7 to determine whether the WaitNextEvent function is available.

Listing 9-8 Checking for the availability of the WaitNextEvent function

FUNCTION WNEAvailable: Boolean;
CONST
            _WaitNextEvent    = $A860;    {trap number of WaitNextEvent}
BEGIN
            WNEAvailable :=  TrapAvailable(_WaitNextEvent);
END;
The NumToolboxTraps function relies on the fact that the InitGraf trap (trap number $A86E) is always implemented. If the trap dispatch table is large enough (that is, has more than $200 entries), then $AA6E always points to either _Unimplemented or something else, but never to InitGraf. As a result, you can check the size of the trap dispatch table by checking to see if the address of trap $A86E is the same as $AA6E.

After receiving the information about the size of the dispatch table, the TrapAvailable function first checks to see if the trap to be tested has a trap number greater than the total number of traps available on the machine. If so, it sets the theTrap variable to _Unimplemented before testing it against the _Unimplemented trap. See the discussion of the trap dispatch table utilities in Inside Macintosh: Operating System Utilities for complete details on trap numbers and the trap dispatch table.

IMPORTANT
There's one final twist in this story. Your software development system might provide glue routines that mimic the operation of some system software routines, thereby allowing you to call them in earlier system software versions. (For instance, MPW versions 3.2 and later provide glue that allows you to call FindFolder in system software versions prior to 7.0.) However, you cannot in general use Gestalt or the technique shown in Listing 9-7 to test for the availability of routines provided as glue. Instead, you'll need to consult the documentation for your development system to find out what glue routines it provides.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
9 JUL 1996